/**************************************************************************************
* GameWorld.java
* 
*************************************************************************************/

package creid.mythos.engine;

import java.io.Serializable;

public class GameWorld implements Serializable
{

	//Constants/////////////////////////////////////////////////////////////////////////

	//Starting terrain
	public static final int START_TERRAIN_TYPE = 8;
	
	//Map IDs
	public static final int OLD_DUNGEON_1 = 0;
	public static final int OLD_DUNGEON_2 = 1;
	public static final int OLD_DUNGEON_3 = 2;
	public static final int OLD_DUNGEON_4 = 3;
	public static final int OLD_DUNGEON_5 = 4;
	
	public static final int OLD_DUNGEON_SIZE = 5;
	public static final int NUM_MAPS = 5;
	
	//Attributes////////////////////////////////////////////////////////////////////////

	private static final long serialVersionUID = 4854668850820615248L;

	//Finished?
	private boolean gameOver;
	
	//The maps 
	private GameMap[] maps;
	
	//Reference to the player
	private Player PC;
	
	//current map
	private int currentMap;

	//Constructors//////////////////////////////////////////////////////////////////////
	
	public GameWorld(Player PC)
	{
		setGameOver(false);
		
		//TODO: Choose background, class?, specialization?
		this.PC = PC;
		
		//TODO: Use a data file to specify dungeons and such

		//maps = new GameMap[NUM_MAPS];
		maps = FileHandler.loadMaps();
		
		currentMap = -1;
		//Old dungeon: the starter dungeon
		
		//int terrain, int x, int y, GameMap map, int targetMap, int targetExit)
		/*Exit[] map0Exits = { new Exit(Terrain.STAIRS_DOWN, GameMap.RANDOM_LOCATION, GameMap.RANDOM_LOCATION, null, OLD_DUNGEON_2, 0) };
		for(Exit ex: map0Exits)
		{
			Terrain.setCellTerrain(ex);
		}
		
		Exit[] map1Exits = { new Exit(Terrain.STAIRS_UP, GameMap.RANDOM_LOCATION, GameMap.RANDOM_LOCATION, null, OLD_DUNGEON_1, 0),
				new Exit(Terrain.STAIRS_DOWN, GameMap.RANDOM_LOCATION, GameMap.RANDOM_LOCATION, null, OLD_DUNGEON_3, 0)};
		for(Exit ex: map1Exits)
		{
			Terrain.setCellTerrain(ex);
		}
		
		maps[0] = new GameMap(0, MapData.DUNGEON, Terrain.DUNGEON_TERRAIN, 1, map0Exits);
		maps[1] = new GameMap(1, MapData.DUNGEON, Terrain.DUNGEON_TERRAIN, 1, map1Exits);*/
	}

	//Methods///////////////////////////////////////////////////////////////////////////

	public boolean isGameOver()
	{
		return gameOver;
	}

	public void setGameOver(boolean gameOver)
	{
		this.gameOver = gameOver;
	}

	public Player getPC()
	{
		return PC;
	}

	public void setPC(Player pC)
	{
		PC = pC;
	}
	
	public GameMap getCurrentMap()
	{
		return maps[currentMap];
	}
	
	public boolean changeMap(int mapNumber, int exitNumber)
	{
		if (mapNumber < -1 || mapNumber >= maps.length)
		{
			Mythos.logger.errorLog("GameWorld.changeMap() called with invalid map ID '" + mapNumber + "'");
			return false;
		}
		
		int old = currentMap;
		
		currentMap = mapNumber;
		
		Cell save = PC.getLocation();
		
		Cell e = maps[currentMap].getExit(exitNumber);

		if (!maps[currentMap].isGenerated())
			maps[currentMap].generate();
		
		if (old > -1)
		{
			maps[old].removeActor(PC);
		
			//Adjacent creatures (who are not neutral or unaware) will follow you to the next map
			int ax = Mythos.callRNG(1);
			int ay = Mythos.callRNG(1);
			int oldAY = ay;
			
			if (ax == 0)
				ax = -1;
			if (ay == 0)
				ay = -1;
			
			int dx = ax * -1;
			int dy = ay * -1;
			int sx = 2 * dx;
			int sy = 2 * dy;
			
			//Grab the adjacent actors
			for (; ax != sx; ax += dx)
			{
				for (ay = oldAY; ay != sy; ay += dy)
				{
					if (ax == 0 && ay == 0)
						continue;
					System.out.println(ax + ", " + ay);
					Cell check = maps[old].getRelativeLocation(save, ax, ay);
					if (check.isOccupied())
					{
						//Move them to the follow queue
						Actor follower = maps[old].removeActor(check.getOccupant());
						follower.setLocation(e);
						maps[currentMap].getFollowQueue().add(follower);
					}
				}
			}
			
			//Heal any monsters left; if you run from the level (and they didn't follow you) everyone quaffs a potion of healing
			maps[old].cleanUp();
		}
		else //Starting a new game
		{
			e = maps[currentMap].findStartingLocation();
		}
		

		maps[currentMap].placeActor(PC, e.getX(), e.getY());
		//Place adjacent creatures
		maps[currentMap].placeFollowers();
		
		maps[currentMap].updateFOV(PC.getLocation());
		
		return true;
	}
}
